package com.pilipili.serverapi.video.service;


import com.pilipili.common.Exception.BusinessRuntimeException;
import com.pilipili.common.controller.PageCommResult;
import com.pilipili.common.service.AbstractService;
import com.pilipili.common.util.BeanUtils;
import com.pilipili.serverapi.ErrorCode;
import com.pilipili.serverapi.video.dto.req.VideoSearchDto;
import com.pilipili.serverapi.video.dto.req.VideoUploadDto;
import com.pilipili.serverapi.video.dto.resp.VideoSearchResultDto;
import com.pilipili.serverapi.video.entity.Video;
import com.pilipili.serverapi.video.repository.VideoRepository;
import com.pilipili.serverapi.video.util.VideoUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

/**
 * 视频管理Service
 *
 * @author chen.guosheng
 */
@Service
@PropertySource({"classpath:application.yml"})
public class VideoService extends AbstractService<VideoRepository, Video, Long> {

    @Value("${savePath.videoOriFilePath}")
    private String videoOriFilePath;

    @Value("${savePath.videoFilePath}")
    private String videoFilePath;

    @Value("${savePath.videoRequestPath}")
    private String videoRequestPath;

    @Autowired
    private VideoUtil videoUtil;

    /**
     * 多条件搜索视频
     * @param videoSearchDto
     * @return
     */
    public PageCommResult<VideoSearchResultDto> search(VideoSearchDto videoSearchDto){
        List<Video> videos = this.repository.search(videoSearchDto);
        List<VideoSearchResultDto> results = new ArrayList<>();
        BeanUtils.copyListProperties(videos, results, VideoSearchResultDto.class);
        Long total = this.repository.countSearch(videoSearchDto);
        return PageCommResult.successPageResult(results, videoSearchDto.getPage().getStart(),
                videoSearchDto.getPage().getCount(), total);
    }


    @Transactional
    public void uploadVideo(VideoUploadDto videoUploadDto, MultipartFile videoOriFile) throws IOException{
        saveVideoOriFile(videoUploadDto.getUserId(), videoOriFile);
        String[] str = videoOriFile.getOriginalFilename().split("\\.");
        String fileName = str[0];
        Video video = new Video();
        BeanUtils.copyProperties(videoUploadDto, video);
        video.setVideoOri(videoOriFile.getOriginalFilename());
        video.setVideoUrl(videoRequestPath+videoUploadDto.getUserId()+"_"+fileName+"/"+fileName+".m3u8");
        video.setPreviewImageUrl(videoRequestPath+videoUploadDto.getUserId()+"_"+fileName+"/"+fileName+".jpg");
        this.repository.save(video);
        Video video1 = this.repository.findByUserIdAndTitle(video.getUserId(), video.getTitle());
        videoUtil.transcodeToM3U8(videoOriFile, video1);

    }

    @Transactional
    public void saveVideoOriFile(Long userId, MultipartFile videoOriFile) throws IOException {
        File file = new File(videoOriFilePath + userId.toString()+"/"+videoOriFile.getOriginalFilename());
        File parentFile = file.getParentFile();
        if(!parentFile.exists()){
            parentFile.mkdirs();
        }
        file.createNewFile();
        videoOriFile.transferTo(file);
    }

    @Transactional
    public void videoAudit(Long videoId, Long auditState){
        if(auditState != 0L && auditState != 1L && auditState != -1L){
            throw new BusinessRuntimeException(ErrorCode.AUDIT_STATE_ERROR);
        }
        Video video = this.find(videoId);
        if(video != null) {
            video.setAuditState(auditState);
            this.repository.save(video);
        }
    }

    @Transactional
    public void batchDelete(List<Long> videoIds){
        for(Long videoId : videoIds){
            Video video = this.find(videoId);
            if(video != null){
                if(video.getTransState() == 0L){
                    throw new BusinessRuntimeException(ErrorCode.VIDEO_DELETE_REJECT);
                }
            }
        }
        for(Long videoId : videoIds){
            Video video = this.find(videoId);
            if(video != null){
                String[] str = video.getVideoOri().split("\\.");
                String fileName = str[0];
                String videoOriFileDeletePath = videoOriFilePath + video.getUserId() + "/" + video.getVideoOri();
                String videoDirPath = videoFilePath + video.getUserId() + "_" + fileName;
                File videoOriFile = new File(videoOriFileDeletePath);
                File videoDir = new File(videoDirPath);
                delFile(videoOriFile);
                delFile(videoDir);
            }
        }
        this.repository.deleteByIdIn(videoIds);
    }

    @Transactional
    boolean delFile(File file) {
        if (!file.exists()) {
            return false;
        }

        if (file.isDirectory()) {
            File[] files = file.listFiles();
            for (File f : files) {
                delFile(f);
            }
        }
        return file.delete();
    }

}
